package com.atguigu.tingshu.user.service.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import com.atguigu.tingshu.album.client.TrackInfoFeignClient;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.rabbit.constant.MqConst;
import com.atguigu.tingshu.common.rabbit.service.RabbitService;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.common.result.ResultCodeEnum;
import com.atguigu.tingshu.common.util.AuthContextHolder;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.user.*;
import com.atguigu.tingshu.user.config.WeChatMpConfig;
import com.atguigu.tingshu.user.mapper.*;
import com.atguigu.tingshu.user.service.UserInfoService;
import com.atguigu.tingshu.user.service.UserPaidTrackService;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.atguigu.tingshu.vo.user.UserPaidRecordVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.joda.time.LocalDate;
import org.joda.time.LocalDateTime;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"all"})
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {

	@Autowired
	private UserInfoMapper userInfoMapper;

	@Autowired
	private WxMaService wxMaService;

	@Autowired
	private RedisTemplate redisTemplate;

	@Autowired
	private RabbitService rabbitService;

	@Autowired
	private UserPaidTrackMapper userPaidTrackMapper;

	@Autowired
	private UserPaidAlbumMapper userPaidAlbumMapper;

	@Autowired
	private UserVipServiceMapper userVipServiceMapper;

	@Autowired
	private VipServiceConfigMapper vipServiceConfigMapper;

	@Autowired
	private TrackInfoFeignClient trackInfoFeignClient;

	@Override
	public HashMap<String, Object> wxLogin(String code) {
//		创建一个HashMap去存储openId
		HashMap<String, Object> map = new HashMap<>();
//		调用微信小程序的api获取openId
		WxMaJscode2SessionResult sessionInfo = null;
		try {
			sessionInfo = wxMaService.getUserService().getSessionInfo(code);
		} catch (WxErrorException e) {
			throw new RuntimeException(e);
		}
//		开始判断是否已经注册
		UserInfo userInfo = userInfoMapper.selectOne(new LambdaQueryWrapper<UserInfo>().eq(UserInfo::getWxOpenId, sessionInfo.getOpenid()));
		if (ObjectUtils.isEmpty(userInfo)){
//			如果是空的话,就创建一个新的userInfo对象
			userInfo = new UserInfo();
//			给userInfo设置属性
			userInfo.setNickname("用户"+System.currentTimeMillis());
			userInfo.setWxOpenId(sessionInfo.getOpenid());
			userInfo.setAvatarUrl("https://oss.aliyuncs.com/aliyun_id_photo_bucket/default_handsome.jpg");
//			设置完属性后就将其保存到数据库中
			userInfoMapper.insert(userInfo);
//			注册成功后,就发送一个异步消息,用于再登录后给用户赋新的值
			rabbitService.sendMessage(MqConst.QUEUE_USER_REGISTER,MqConst.ROUTING_USER_REGISTER,userInfo.getId());
		}
//		生成一个token
		String token = UUID.randomUUID().toString().replaceAll("-","");
//		将userInfo数据放入到redis中
//		设置redis中的key
		String loginKey = RedisConstant.USER_LOGIN_KEY_PREFIX + token;
		redisTemplate.opsForValue().set(loginKey, userInfo, RedisConstant.USER_LOGIN_KEY_TIMEOUT, TimeUnit.SECONDS);
//		将token放入到map中
		map.put("token", token);
		return map;
	}

	@Override
	public UserInfoVo getUserIinfo(Long userId) {
//		根据id获取用户信息
		UserInfo userInfo = this.getById(userId);
//		创建一个新的UserInfoVo对象
		UserInfoVo userInfoVo = new UserInfoVo();
//		属性拷贝
		BeanUtils.copyProperties(userInfo,userInfoVo);
//		返回对应对象
		return userInfoVo;
	}

	@Override
	public void updateUser(UserInfoVo userInfoVo) {
//		创建一个新的userInfo对象
		UserInfo userInfo = new UserInfo();
//		属性拷贝
		BeanUtils.copyProperties(userInfoVo,userInfo);
//		更新数据库信息
		this.updateById(userInfo);
	}

	@Override
	public Map<Long, Integer> userIsPaidTrack(Long albumId, List<Long> trackIdList) {
//		创建一个返回的map对象
		Map<Long, Integer> map = new HashMap<>();
//		从线程上获取用户id
		Long userId = AuthContextHolder.getUserId();
//		先判断是否购买了专辑
		UserPaidAlbum userPaidAlbum = userPaidAlbumMapper.selectOne(new LambdaQueryWrapper<UserPaidAlbum>().eq(UserPaidAlbum::getAlbumId, albumId).eq(UserPaidAlbum::getUserId, userId));
		if (!ObjectUtils.isEmpty(userPaidAlbum)){
//			如果不为空,说明购买了专辑
			return trackIdList.stream().collect(Collectors.toMap(trackId -> trackId, trackId -> 1));
		}else {
			if (!ObjectUtils.isEmpty(trackIdList)){
//			根据对应的信息去查询
				List<UserPaidTrack> userPaidTracks = userPaidTrackMapper.selectList(new LambdaQueryWrapper<UserPaidTrack>().eq(UserPaidTrack::getUserId, userId).eq(UserPaidTrack::getAlbumId, albumId).in(UserPaidTrack::getTrackId, trackIdList));

//			将查询出来的信息转换并且放入到map中
//				map = userPaidTracks.stream().collect(Collectors.toMap(userPaidTrack -> userPaidTrack.getTrackId(), userPaidTrack -> 1));
				List<Long> collect = userPaidTracks.stream().map(userPaidTrack -> userPaidTrack.getTrackId()).collect(Collectors.toList());
				for (Long id : trackIdList) {
					if (collect.contains(id)){
						map.put(id,1);
					}else {
						map.put(id,0);
					}
				}
			}
		}
		return map;
	}

	/**
	 * 判断用户是否支付了指定的专辑
	 *
	 * @param albumId 专辑ID，用于标识特定的专辑
	 * @param userId 用户ID，用于标识特定的用户
	 * @return 返回一个布尔值，如果用户支付了指定的专辑则返回true，否则返回false
	 */
	@Override
	public Boolean isPaidAlbum(Long albumId, Long userId) {
	    // 创建一个Lambda查询包装器，用于查询用户支付的专辑
	    LambdaQueryWrapper<UserPaidAlbum> queryWrapper = new LambdaQueryWrapper<UserPaidAlbum>()
	        .eq(UserPaidAlbum::getAlbumId, albumId)
	        .eq(UserPaidAlbum::getUserId, userId);

	    // 使用查询包装器从数据库中选择一条记录
	    UserPaidAlbum userPaidAlbum = userPaidAlbumMapper.selectOne(queryWrapper);

	    // 根据查询结果判断用户是否支付了指定的专辑
	    return userPaidAlbum == null ? false : true;
	}

	@Override
	public List<Long> findAllPaidTracks(Long albumId, Long userId) {
//		获取所有的付费的TrackId
		List<Long> list = userPaidTrackMapper.selectList(new LambdaQueryWrapper<UserPaidTrack>().eq(UserPaidTrack::getUserId, userId).eq(UserPaidTrack::getAlbumId, albumId)).stream().map(userPaidTrack -> userPaidTrack.getTrackId()).collect(Collectors.toList());
//		将数据返回
		return list;
	}

	@Override
	public Boolean saveUserPaidRecord(UserPaidRecordVo userPaidRecordVo) {
		int rows = 0;
		try {
//		先判断购买的类型
			if (SystemConstant.ORDER_ITEM_TYPE_ALBUM.equals(userPaidRecordVo.getItemType())){
				UserPaidAlbum userPaidAlbum1  = new UserPaidAlbum();
				//			表示购买的专辑
	//			先找一下之前是否购买了此专辑
				UserPaidAlbum userPaidAlbum = userPaidAlbumMapper.selectById(userPaidRecordVo.getItemIdList().get(0));
				if (!ObjectUtils.isEmpty(userPaidAlbum)){
	//				表示购买过此专辑
					throw new GuiguException(20001, "您已经购买了该专辑");
				}
	//			给userPaidAlbum的属性赋值
				userPaidAlbum1.setUserId(userPaidRecordVo.getUserId());
				userPaidAlbum1.setOrderNo(userPaidRecordVo.getOrderNo());
				userPaidAlbum1.setAlbumId(userPaidRecordVo.getItemIdList().get(0));
	//			调用mapper层方法去插入数据
				rows =  userPaidAlbumMapper.insert(userPaidAlbum1);

			}else if (SystemConstant.ORDER_ITEM_TYPE_TRACK.equals(userPaidRecordVo.getItemType())){
//				先获取trackInfo信息
				Result<TrackInfo> trackInfoResult = trackInfoFeignClient.getTrackInfo(userPaidRecordVo.getItemIdList().get(0));
				Assert.notNull(trackInfoResult, "查询声音失败");
//				获取对应的trackInfo数据
				TrackInfo trackInfo = trackInfoResult.getData();
				Assert.notNull(trackInfo, "查询声音失败");
				//			表示购买的音频
				for (Long itemId : userPaidRecordVo.getItemIdList()) {
	//				生成一个新的UserpaidTrack对象
						UserPaidTrack userPaidTrack = new UserPaidTrack();
	//				为属性赋值
						userPaidTrack.setUserId(userPaidRecordVo.getUserId());
						userPaidTrack.setOrderNo(userPaidRecordVo.getOrderNo());
						userPaidTrack.setAlbumId(trackInfo.getAlbumId());
						userPaidTrack.setTrackId(itemId);
	//				调用方法插入数据
						rows += userPaidTrackMapper.insert(userPaidTrack);
				}
			}else {
	//			表示购买的是vip
	//			先查看当前用户的vip有没有过期
				UserInfo userInfo = userInfoMapper.selectById(userPaidRecordVo.getUserId());
				//				先查出买的时间是多长
				VipServiceConfig vipServiceConfig = vipServiceConfigMapper.selectById(userPaidRecordVo.getItemIdList().get(0));
				//				更新userVipService表
				UserVipService userVipService = new UserVipService();
	//			生成一个最新的时间
				Date newVipExpireTime = null;
				if (userInfo.getIsVip()==1 && userInfo.getVipExpireTime().after(new Date())){
	//				表示现在vip没有过期，是续费
	//				获取过期时间
					Date vipExpireTime = userInfo.getVipExpireTime();
	//				使用localDateTime去使月份相加减
					LocalDateTime localDateTime = new LocalDateTime(vipExpireTime);
	//				计算出新的过期时间
					newVipExpireTime = localDateTime.plusMonths(vipServiceConfig.getServiceMonth()).toDate();
				}else {
	//				表示现在vip已经过期，需要重新购买
	//				给属性赋值
					userVipService.setUserId(userPaidRecordVo.getUserId());
					userVipService.setOrderNo(userPaidRecordVo.getOrderNo());
					userVipService.setStartTime(new Date());
	//				使用localDateTime计算出新的过期时间
					LocalDateTime localDateTime = new LocalDateTime(new Date());
					newVipExpireTime = localDateTime.plusMonths(vipServiceConfig.getServiceMonth()).toDate();
					userInfo.setIsVip(1);
				}
				//				为属性赋值
				userVipService.setUserId(userPaidRecordVo.getUserId());
				userVipService.setOrderNo(userPaidRecordVo.getOrderNo());
				userVipService.setStartTime(new Date());
				userVipService.setExpireTime(newVipExpireTime);
	//				调用mapper层方法去添加
				rows += userVipServiceMapper.insert(userVipService);
	//				同时去更改userInfo表中的过期时间
				userInfo.setVipExpireTime(newVipExpireTime);
	//				更新userInfo中的属性
				this.updateById(userInfo);
			}
		} catch (GuiguException e) {
			e.getMessage();
		}
		if (rows>0){
			return true;
		}
		return null;
	}
}
